package users

import (
	"encoding/json"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize"
	"go_auth/ext/e"
	"go_auth/ext/jwt"
	"go_auth/ext/settings"
	"go_auth/models/users"
	"go_auth/utils/commons"
	"go_auth/utils/redis"
	"go_auth/utils/topt"
	"io"
	"strings"
)

type User struct {
	users.User
}

type SetPerKey struct {
	Uid string `json:"uid"`
	//Method string   `json:"method"`
	PerId []string `json:"per_id"`
}

func (u *User) Login(sourceId1, key string) (sourceId, uid string, flag bool, code int, arr []string) {
	staff := 0
	staff, sourceId, uid, code, flag = users.Login(u.UserName, u.Password, sourceId1)

	if staff == 1 {
		//CheckCodeIsOk
		b, uid_key := CheckCertCode(uid)
		if !b {
			return sourceId, uid, false, e.CheckCodeError, arr
		}
		if key != fmt.Sprint(topt.ReturnCode(uid_key)) {
			return sourceId, uid, false, e.CheckCodeTimeOut, arr
		}

		perId := GetUserRedisPer(uid)
		for _, v := range perId {
			value, _ := redis.GetValue(v, settings.RDb3)
			arr = append(arr, value)
		}
		return sourceId, uid, flag, code, arr

	}

	return sourceId, uid, flag, code, nil

}

func (u *User) Register(sourceId string) int64 {

	return users.Register(u.UserName, u.Password, sourceId)
}

func (u *User) FindUsers(size int) (interface{}, int64) {

	return users.FindUsers(size)
}

func (u *User) UpdatePassword() int64 {
	return u.User.UpdatePassword()
}

func (u *User) SetAdmin() int64 {
	code := u.User.SetAdmin()
	if code <= settings.Zero {
		return code
	}
	if u.Staff == 1 {
		AddCertCode(u.Uid)
	} else {
		DeleteCertCode(u.Uid)
	}

	return code

}

func (u *User) ImportUser(r io.Reader) bool {
	lsx, err := excelize.OpenReader(r)
	if !commons.CheckErr(err) {
		return false
	}

	rows := lsx.GetRows("用户注册")
	for count, row := range rows {
		if count > 0 {
			var data []string
			for _, cell := range row {
				data = append(data, cell)
			}
			//uid := commons.EncodeMd5(data[0] + data[1] + data[2] + settings.JwtBase.JwtSecret)

			b := users.Register(data[0], data[1], data[2])
			fmt.Println(b, data[0], data[1], data[2])
			//if !b {
			//	return false
			//}
		}
	}
	return true
}

/**
校验权限
*/

func CheckPer(uid, uri, method string) int {

	//if auth.ExistUserSourceByUid(uid) == conf.STRING_FLAG {
	//	//用户不存在
	//	return e.USER_NOT_EXIST
	//}
	per := GetUserRedisPer(uid)
	bytes, ex := redis.GetValue(uri, settings.RDb0)
	if !commons.CheckErr(ex) {
		return e.PerNotExist
	}
	if per == nil {
		return e.UserNotExist
	} else {
		if commons.BinarySearch(per, commons.StringJoin([]string{string(bytes), "_", method})) == -1 {
			return e.UserPerNoAllow
		}
	}
	return e.Success
}

func GetUserRedisPer(uid string) []string {
	value, err := redis.GetValue(settings.PrefixPer+uid, settings.RDb2)
	var s *SetPerKey
	if commons.CheckErr(err) {
		str := strings.Replace(string(value), "\\", "", -1)
		//unmarshal := json.Unmarshal([]byte(str[1:len(str)-1]), &s)
		unmarshal := json.Unmarshal([]byte(str), &s)

		print(unmarshal)
		return s.PerId

	}
	return nil
}

func GetAllUserPer() {
	per, err := users.GetAllUserPer()
	print("per")
	if commons.CheckErr(err) {
		m := make(map[string][]string)
		for _, v := range per {
			m[v["uid"]] = append(m[v["uid"]], v["per_id"]+"_"+v["method"])
		}
		for uid, v := range m {
			s := SetPerKey{}
			s.Uid = uid
			s.PerId = v
			marshal, _ := json.Marshal(&s)
			redis.SetStringValue(settings.PrefixPer+uid, string(marshal), 60*60*24*30*36, settings.RDb2)
		}

	}
}

func CheckToken(token, uri, method string) int {

	claims, err, flag := jwt.ParseToken(token)
	//claims含有用户信息
	if err != nil {

		return flag
	}
	//从redis中找这个用户对应的token是否存在(如果不存在,用户可能退出)
	/*
		如果这里能查出来token,说明用户存在   xxxx:当时不知道为嘛脑残了
	*/
	uid := claims.Uid
	if dbToken, err := redis.GetValue(commons.StringJoin([]string{settings.PrefixToken, uid, "_", claims.SourceId}), settings.RDb1); err != nil {
		return e.TokenError
	} else if token != dbToken {
		return e.UserLoginInOther
	}

	code := CheckPer(uid, uri, method)
	if code != e.Success {
		return code
	}

	return e.Success
}
